//
//  MySQLParameter.m
//  LibMySQL
//
//  Created by Marcus Grenängen on 2009-08-04.
//  Copyright 2009 SneWs Soft. All rights reserved.
//
#import "MySQLParameter.h"


@implementation MySQLParameter

@synthesize isNull, value, dataType, length;


+ (MySQLParameter*)parameterWithValue:(id)v asType:(NSInteger)t {
	return [[MySQLParameter alloc] initWithValue: v andType: t];
	
} // END STATIC METHOD: parameterWithValue: 

+ (MySQLParameter*)parameterWithLong:(long)v {
	return [[MySQLParameter alloc] initWithValue: [NSNumber numberWithLong: v] andType: MYSQL_TYPE_LONG];
}

+ (MySQLParameter*)parameterWithInt:(int)v {
	return [[MySQLParameter alloc] initWithValue: [NSNumber numberWithInt: v] andType: MYSQL_TYPE_INT24];
}

+ (MySQLParameter*)parameterWithShort:(short)v {
	return [[MySQLParameter alloc] initWithValue: [NSNumber numberWithShort: v] andType: MYSQL_TYPE_SHORT];
}

+ (MySQLParameter*)parameterWithString:(NSString *)v {
	return [[MySQLParameter alloc] initWithValue: v andType: MYSQL_TYPE_STRING];
}

+ (MySQLParameter*)parameterWithEnum:(char)v {
	return [[MySQLParameter alloc] initWithValue: [NSString stringWithUTF8String: &v] andType: MYSQL_TYPE_ENUM];
}




/*
 *
 */
- (id)initWithValue:(id)v {
	return [self initWithValue: v andType: -1];

} // END METHOD: initWithValue: 

/*
 *
 */
- (id)initWithValue:(id)v andType:(NSInteger)t {
	if( self = [super init] ) {
		value = [v retain];
		
		// Lazy init for guessing data type if it's not specified.
		dataType = t;
		isNull = FALSE;
		length = 0;
		
	} // END if( self = [super init] )
	
	return self;
	
} // END METHOD: initWithValue: 

- (NSString *)stringValue {
	NSString *retVal = nil;
	switch( dataType ) {
		case MYSQL_TYPE_NULL:
			retVal = @"NULL";
			break;
			
		case MYSQL_TYPE_STRING:
			retVal = [value copy];
			break;
			
		case MYSQL_TYPE_DATETIME:
			/// TODO: Use correct locale descriptor instead of nil.
			retVal = [value descriptionWithLocale: nil];
			break;
			
		default:
			if( [value isKindOfClass: [NSNumber class]] )
				retVal = [value stringValue];
			break;
	
	} // END switch( dataType )
	
	return retVal;

} // END METHOD: stringValue: 


/// This method will be declared in MySQLConnection since it's the
/// only place we will be calling it from.
- (unsigned int) _guessDataType {
	if( value == nil || [value isKindOfClass: [NSNull class]] ) {
		isNull = TRUE;
		dataType = MYSQL_TYPE_NULL;
		
		// Nothing more to process
		return dataType;
		
	} // END if( value == nil || [value isKindOfClass: [NSNull class]] )
	
	if( dataType > 0 ) {
		// The type is alread set, just exit
		return dataType;
	
	} // END if( dataType > 0 )
	
	// From here, we are supposed to guess what MySQL data type we should
	// transform the value to.
	
	isNull = FALSE;
	if( [value isKindOfClass: [NSString class]] ) {
		dataType = MYSQL_TYPE_STRING;
		length = [value length];
		
	} // END if( [value isKindOfClass: [NSString class]] )
	else if( [value isKindOfClass: [NSDate class]] ) {
		dataType = MYSQL_TYPE_DATETIME;
		
	} // END else if( [value isKindOfClass: [NSString class]] )
	else if( [value isKindOfClass: [NSNumber class]] ) {
		
		/// TODO: This feels way to complicated, there must be a
		/// much simpler way to perform this guess.
		
		NSNumber* tn = (NSNumber*)value;
		
		const char* tmp = [[tn stringValue] UTF8String];
		char* last = (char*)&tmp[(int)strlen( tmp )];
		
		char* outEnd = NULL;
		float f = strtof( tmp, &outEnd );
		if( outEnd == last && f != 0 )
			dataType = MYSQL_TYPE_FLOAT;
		
		double d = strtod( tmp, &outEnd );
		if( outEnd == last && d != 0 )
			dataType = MYSQL_TYPE_DOUBLE;
		
		free( &tmp );
		
		// Still no match, make it a integer and check size
		int i = [tn intValue];
		if( i <= INT8_MAX && i >= INT8_MIN )
			dataType = MYSQL_TYPE_SHORT;
		else if( i <= INT32_MAX && i >= INT32_MIN )
			dataType = MYSQL_TYPE_INT24;
	
	} // END else if( [value isKindOfClass: [NSNumber class]] )
	
	return dataType;
	
} // END METHOD: _guessDataType: 


/*
 * 
 * 
 */
+ (NSArray*)_parseArgListWithCommands:(MySQLParameter *)firstObject withList:(va_list)args {
	MySQLParameter *parameter = nil;
	NSMutableArray *params = [[NSMutableArray alloc] init];
	@try {
		for( parameter = firstObject; parameter != nil; parameter = va_arg( args, MySQLParameter* ) ) {
			[params addObject: parameter];
			
			[parameter _guessDataType];
			NSLog( @"Parameter guessed data type info - Is Null ? %@, Value type: %li",
				  ( [parameter isNull] ? @"YES" : @"NO" ), [parameter dataType] );
			
			[parameter release];
			
		} // END for( parameter = sqlCommand; parameter != nil; parameter = va_arg( args, MySQLParameter* ) )
		
	} // END try
	@catch( NSException *error ) {
		[error release];
		NSLog( @"Error building MySQL Parameter list: %@", error );
		
	} // END @catch( NSException *error )
	@finally {		
		[parameter release];
		
	} // END @finally
	
	return params;

} // END STATIC METHOD: _parseArgListWithCommands: 


@end








